/*
 * This file is part of Cadmium.
 * Copyright (C) 2007-2010 Xavier Clerc.
 *
 * Cadmium is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Cadmium is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package fr.x9c.cadmium.primitives.cadmiumjdbc;

import java.sql.ResultSet;
import java.sql.Statement;

import fr.x9c.cadmium.kernel.Block;
import fr.x9c.cadmium.kernel.CodeRunner;
import fr.x9c.cadmium.kernel.Custom;
import fr.x9c.cadmium.kernel.Fail;
import fr.x9c.cadmium.kernel.Primitive;
import fr.x9c.cadmium.kernel.PrimitiveProvider;
import fr.x9c.cadmium.kernel.Value;
import fr.x9c.cadmium.primitives.cadmium.Cadmium;

/**
 * This class provides the primitives related to the <tt>java.sql.Statement</tt> class.
 *
 * @author <a href="mailto:cadmium@x9c.fr">Xavier Clerc</a>
 * @version 1.1
 * @since 1.1
 */
@PrimitiveProvider
public final class Statements {

    /**
     * No instance of this class.
     */
    private Statements() {
    } // end empty constructor

    /**
     * Adds a SQL command to the passed statement.
     * @param ctxt context
     * @param statement statement
     * @param sql sql command
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_add_batch(final CodeRunner ctxt,
                                                        final Value statement,
                                                        final Value sql)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.addBatch(sql.asBlock().asString());
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_add_batch(CodeRunner, Value, Value)'

    /**
     * Cancels the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_cancel(final CodeRunner ctxt,
                                                     final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.cancel();
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_cancel(CodeRunner, Value)'

    /**
     * Empties the list of SQL commands for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_clear_batch(final CodeRunner ctxt,
                                                          final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.clearBatch();
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_clear_batch(CodeRunner, Value)'

    /**
     * Clears the warnings for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_clear_warnings(final CodeRunner ctxt,
                                                             final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.clearWarnings();
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_clear_warnings(CodeRunner, Value)'

    /**
     * Closes the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_close(final CodeRunner ctxt,
                                                    final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.close();
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_close(CodeRunner, Value)'

    /**
     * Executes a SQL statement.
     * @param ctxt context
     * @param statement statement
     * @param sql SQL statement to execute
     * @return <tt>true</tt> if the first result is a result set object,
     *         <tt>false</tt> otherwise (update count of absence of result)
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute(final CodeRunner ctxt,
                                                      final Value statement,
                                                      final Value sql)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return s.execute(sql.asBlock().asString())
                ? Value.TRUE
                : Value.FALSE;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute(CodeRunner, Value, Value)'

    /**
     * Executes a SQL statement.
     * @param ctxt context
     * @param statement statement
     * @param sql SQL statement to execute
     * @param autogen whether auto-generated keys should be retrievable
     * @return <tt>true</tt> if the first result is a result set object,
     *         <tt>false</tt> otherwise (update count of absence of result)
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute_autogen(final CodeRunner ctxt,
                                                              final Value statement,
                                                              final Value sql,
                                                              final Value autogen)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return s.execute(sql.asBlock().asString(),
                             Misc.decodeStatementAutogenKeys(autogen))
                ? Value.TRUE
                : Value.FALSE;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute_autogen(CodeRunner, Value, Value, Value)'

    /**
     * Executes a SQL statement.
     * @param ctxt context
     * @param statement statement
     * @param sql SQL statement to execute
     * @param indexes list of column indexes that should be retrievable
     * @return <tt>true</tt> if the first result is a result set object,
     *         <tt>false</tt> otherwise (update count of absence of result)
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute_idx(final CodeRunner ctxt,
                                                          final Value statement,
                                                          final Value sql,
                                                          final Value indexes)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return s.execute(sql.asBlock().asString(),
                             Misc.decodeIntList(indexes))
                ? Value.TRUE
                : Value.FALSE;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute_idx(CodeRunner, Value, Value, Value)'

    /**
     * Executes a SQL statement.
     * @param ctxt context
     * @param statement statement
     * @param sql SQL statement to execute
     * @param names list of column names that should be retrievable
     * @return <tt>true</tt> if the first result is a result set object,
     *         <tt>false</tt> otherwise (update count of absence of result)
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute_name(final CodeRunner ctxt,
                                                           final Value statement,
                                                           final Value sql,
                                                           final Value names)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return s.execute(sql.asBlock().asString(),
                             Misc.decodeStringList(names))
                ? Value.TRUE
                : Value.FALSE;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute_name(CodeRunner, Value, Value, Value)'

    /**
     * Executes a batch of SQL commands.
     * @param ctxt context
     * @param statement statement
     * @return list of update counts (one per command in the batch)
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute_batch(final CodeRunner ctxt,
                                                            final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return Misc.encodeStatementResultList(s.executeBatch());
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute_batch(CodeRunner, Value)'

    /**
     * Executes a SQL query.
     * @param ctxt context
     * @param statement statement
     * @param sql SQL query
     * @return query result set
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute_query(final CodeRunner ctxt,
                                                            final Value statement,
                                                            final Value sql)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final ResultSet res = s.executeQuery(sql.asBlock().asString());
            return Cadmium.createObject(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute_query(CodeRunner, Value, Value)'

    /**
     * Executes a SQL statement (either a <i>INSERT</i>, <i>UPDATE</i> or
     * <i>DELETE</i> query).
     * @param ctxt context
     * @param statement statement
     * @param sql SQL statement
     * @return update count
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute_update(final CodeRunner ctxt,
                                                             final Value statement,
                                                             final Value sql)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final Block res = Block.createCustom(Custom.INT_32_SIZE,
                                                 Custom.INT_32_OPS);
            res.setInt32(s.executeUpdate(sql.asBlock().asString()));
            return Value.createFromBlock(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute_update(CodeRunner, Value, Value)'

    /**
     * Executes a SQL <i>UPDATE</i> statement.
     * @param ctxt context
     * @param statement statement
     * @param sql SQL statement
     * @param autogen whether auto-generated keys should be retrievable
     * @return update count
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute_update_autogen(final CodeRunner ctxt,
                                                                     final Value statement,
                                                                     final Value sql,
                                                                     final Value autogen)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final Block res = Block.createCustom(Custom.INT_32_SIZE,
                                                 Custom.INT_32_OPS);
            res.setInt32(s.executeUpdate(sql.asBlock().asString(),
                                         Misc.decodeStatementAutogenKeys(autogen)));
            return Value.createFromBlock(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute_update_autogen(CodeRunner, Value, Value, Value)'

    /**
     * Executes a SQL <i>UPDATE</i> statement.
     * @param ctxt context
     * @param statement statement
     * @param sql SQL statement
     * @param indexes list of column indexes that should be retrievable
     * @return update count
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute_update_idx(final CodeRunner ctxt,
                                                                 final Value statement,
                                                                 final Value sql,
                                                                 final Value indexes)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final Block res = Block.createCustom(Custom.INT_32_SIZE,
                                                 Custom.INT_32_OPS);
            res.setInt32(s.executeUpdate(sql.asBlock().asString(),
                                         Misc.decodeIntList(indexes)));
            return Value.createFromBlock(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute_update_idx(CodeRunner, Value, Value, Value)'

    /**
     * Executes a SQL <i>UPDATE</i> statement.
     * @param ctxt context
     * @param statement statement
     * @param sql SQL statement
     * @param names list of column names that should be retrievable
     * @return update count
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_execute_update_name(final CodeRunner ctxt,
                                                                  final Value statement,
                                                                  final Value sql,
                                                                  final Value names)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final Block res = Block.createCustom(Custom.INT_32_SIZE,
                                                 Custom.INT_32_OPS);
            res.setInt32(s.executeUpdate(sql.asBlock().asString(),
                                         Misc.decodeStringList(names)));
            return Value.createFromBlock(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_execute_update_name(CodeRunner, Value, Value, Value)'

    /**
     * Returns the fetch direction for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the fetch direction for the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_fetch_direction(final CodeRunner ctxt,
                                                                  final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return Misc.encodeResultSetFetchDirection(s.getFetchDirection());
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_fetch_direction(CodeRunner, Value)'

    /**
     * Returns the fetch size for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the fetch size for the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_fetch_size(final CodeRunner ctxt,
                                                             final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final Block res = Block.createCustom(Custom.INT_32_SIZE,
                                                 Custom.INT_32_OPS);
            res.setInt32(s.getFetchSize());
            return Value.createFromBlock(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_fetch_size(CodeRunner, Value)'

    /**
     * Returns the list of auto-generated keys for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the list of auto-generated keys for the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_generated_keys(final CodeRunner ctxt,
                                                                 final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final ResultSet res = s.getGeneratedKeys();
            return Cadmium.createObject(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_generated_keys(CodeRunner, Value)'

    /**
     * Returns the maximum field size for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the maximum field size for the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_max_field_size(final CodeRunner ctxt,
                                                                 final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final Block res = Block.createCustom(Custom.INT_32_SIZE,
                                                 Custom.INT_32_OPS);
            res.setInt32(s.getMaxFieldSize());
            return Value.createFromBlock(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_max_field_size(CodeRunner, Value)'

    /**
     * Returns the maximum number of rows for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the maximum number of rows for the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_max_rows(final CodeRunner ctxt,
                                                           final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final Block res = Block.createCustom(Custom.INT_32_SIZE,
                                                 Custom.INT_32_OPS);
            res.setInt32(s.getMaxRows());
            return Value.createFromBlock(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_max_rows(CodeRunner, Value)'

    /**
     * Tests whether there is more results.
     * @param ctxt context
     * @param statement statement
     * @return <tt>true</tt> if there is a next result set (closes the current one and moves to the next one),
     *         <tt>false</tt> otherwise
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_more_results(final CodeRunner ctxt,
                                                               final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return s.getMoreResults() ? Value.TRUE : Value.FALSE;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_more_results(CodeRunner, Value)'

    /**
     * Tests whether there is more results.
     * @param ctxt context
     * @param statement statement
     * @param current what to do with the current result set
     * @return <tt>true</tt> if there is a next result set,
     *         <tt>false</tt> otherwise
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_more_results_current(final CodeRunner ctxt,
                                                                       final Value statement,
                                                                       final Value current)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return s.getMoreResults(Misc.decodeStatementAction(current)) ? Value.TRUE : Value.FALSE;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_more_results_current(CodeRunner, Value, Value)'

    /**
     * Returns the query timeout for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the query timeout for the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_query_timeout(final CodeRunner ctxt,
                                                                final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final Block res = Block.createCustom(Custom.INT_32_SIZE,
                                                 Custom.INT_32_OPS);
            res.setInt32(s.getQueryTimeout());
            return Value.createFromBlock(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_query_timeout(CodeRunner, Value)'

    /**
     * Returns the current result as a result set.
     * @param ctxt context
     * @param statement statement
     * @return the current result as a result set
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_result_set(final CodeRunner ctxt,
                                                             final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final ResultSet res = s.getResultSet();
            return Cadmium.createObject(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_result_set(CodeRunner, Value)'

    /**
     * Returns the concurrency of result sets returned by the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the concurrency of result sets returned by the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_result_set_concurrency(final CodeRunner ctxt,
                                                                         final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return Misc.encodeResultSetConcurrency(s.getResultSetConcurrency());
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_result_set_concurrency(CodeRunner, Value)'

    /**
     * Returns the holdability of result sets returned by the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the holdability of result sets returned by the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_result_set_holdability(final CodeRunner ctxt,
                                                                         final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return Misc.encodeResultSetHoldability(s.getResultSetHoldability());
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_result_set_holdability(CodeRunner, Value)'

    /**
     * Returns the type of result sets returned by the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the type of result sets returned by the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_result_set_type(final CodeRunner ctxt,
                                                                  final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return Misc.encodeResultSetType(s.getResultSetType());
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_result_set_type(CodeRunner, Value)'

    /**
     * Returns the current result as an update count.
     * @param ctxt context
     * @param statement statement
     * @return the current result as an update count
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_update_count(final CodeRunner ctxt,
                                                               final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            final Block res = Block.createCustom(Custom.INT_32_SIZE,
                                                 Custom.INT_32_OPS);
            res.setInt32(s.getUpdateCount());
            return Value.createFromBlock(res);
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_update_count(CodeRunner, Value)'

    /**
     * Returns the list of SQL warnings for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @return the list of SQL warnings for the passed statement
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_get_warnings(final CodeRunner ctxt,
                                                           final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return Misc.encodeSQLWarnings(s.getWarnings());
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_get_warnings(CodeRunner, Value)'

    /**
     * Tests whether the passed statement is closed.
     * @param ctxt context
     * @param statement statement
     * @return <tt>true</tt> if the passed statement is closed,
     *         <tt>false</tt> otherwise
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_is_closed(final CodeRunner ctxt,
                                                        final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return s.isClosed() ? Value.TRUE : Value.FALSE;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_is_closed(CodeRunner, Value)'

    /**
     * Tests whether the passed statement is poolable.
     * @param ctxt context
     * @param statement statement
     * @return <tt>true</tt> if the passed statement is poolable,
     *         <tt>false</tt> otherwise
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_is_poolable(final CodeRunner ctxt,
                                                          final Value statement)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            return s.isPoolable() ? Value.TRUE : Value.FALSE;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_is_poolable(CodeRunner, Value)'

    /**
     * Sets the cursor name for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @param name cursor name
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_set_cursor_name(final CodeRunner ctxt,
                                                              final Value statement,
                                                              final Value name)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.setCursorName(name.asBlock().asString());
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_set_cursor_name(CodeRunner, Value, Value)'

    /**
     * Sets the escape processing property for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @param v whether escape processing should be enabled
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_set_escape_processing(final CodeRunner ctxt,
                                                                    final Value statement,
                                                                    final Value v)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.setEscapeProcessing(v == Value.TRUE);
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_set_escape_processing(CodeRunner, Value, Value)'

    /**
     * Sets the fetch direction for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @param v fetch direction
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_set_fetch_direction(final CodeRunner ctxt,
                                                                  final Value statement,
                                                                  final Value v)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.setFetchDirection(Misc.decodeResultSetFetchDirection(v));
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_set_fetch_direction(CodeRunner, Value, Value)'

    /**
     * Sets the maximum fetch size for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @param v maximum fetch size
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_set_fetch_size(final CodeRunner ctxt,
                                                             final Value statement,
                                                             final Value v)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.setFetchSize(v.asBlock().asInt32());
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_set_fetch_size(CodeRunner, Value, Value)'

    /**
     * Sets the maximum field size for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @param v maximum field size
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_set_max_field_size(final CodeRunner ctxt,
                                                                 final Value statement,
                                                                 final Value v)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.setMaxFieldSize(v.asBlock().asInt32());
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_set_max_field_size(CodeRunner, Value, Value)'

    /**
     * Sets the maximum number of rows for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @param v maximum number of rows
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_set_max_rows(final CodeRunner ctxt,
                                                           final Value statement,
                                                           final Value v)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.setMaxRows(v.asBlock().asInt32());
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_set_max_rows(CodeRunner, Value, Value)'

    /**
     * Sets the poolable property for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @param v whether statement pool should be enabled
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_set_poolable(final CodeRunner ctxt,
                                                           final Value statement,
                                                           final Value v)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.setPoolable(v == Value.TRUE);
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_set_poolable(CodeRunner, Value, Value)'

    /**
     * Sets the query timeout for the passed statement.
     * @param ctxt context
     * @param statement statement
     * @param v query timeout
     * @return <i>unit</i>
     * @throws Fail.Exception if any error occurs
     */
    @Primitive
    public static Value cadmiumjdbc_statement_set_query_timeout(final CodeRunner ctxt,
                                                                final Value statement,
                                                                final Value v)
        throws Fail.Exception {
        try {
            final Statement s = (Statement) statement.asBlock().asCustom();
            s.setQueryTimeout(v.asBlock().asInt32());
            return Value.UNIT;
        } catch (final Exception e) {
            Cadmium.fail(ctxt, e);
            return Value.UNIT; // never reached
        } // end try/catch
    } // end method 'cadmiumjdbc_statement_set_query_timeout(CodeRunner, Value, Value)'

} // end class 'Statements'
